//	VirtualDub - Video processing and capture application
//	Plugin headers
//	Copyright (C) 1998-2007 Avery Lee, All Rights Reserved.
//
//	The plugin headers in the VirtualDub plugin SDK are licensed differently
//	differently than VirtualDub and the Plugin SDK themselves.  This
//	particular file is thus licensed as follows (the "zlib" license):
//
//	This software is provided 'as-is', without any express or implied
//	warranty.  In no event will the authors be held liable for any
//	damages arising from the use of this software.
//
//	Permission is granted to anyone to use this software for any purpose,
//	including commercial applications, and to alter it and redistribute it
//	freely, subject to the following restrictions:
//
//	1.	The origin of this software must not be misrepresented; you must
//		not claim that you wrote the original software. If you use this
//		software in a product, an acknowledgment in the product
//		documentation would be appreciated but is not required.
//	2.	Altered source versions must be plainly marked as such, and must
//		not be misrepresented as being the original software.
//	3.	This notice may not be removed or altered from any source
//		distribution.

#ifndef f_VD2_PLUGIN_VDVIDEOFILT_H
#define f_VD2_PLUGIN_VDVIDEOFILT_H

#ifdef _MSC_VER
#pragma once
#pragma pack(push, 8)
#endif

#include <stddef.h>

#include "vdplugin.h"

typedef struct VDXHINSTANCEStruct *VDXHINSTANCE;
typedef struct VDXHDCStruct *VDXHDC;
typedef struct VDXHWNDStruct *VDXHWND;

//////////////////

struct VDXScriptObject;
struct VDXFilterVTbls;

//////////////////

enum
{
    /// Request distinct source and destination buffers. Otherwise, the source and destination buffers
    /// alias (in-place mode).
    FILTERPARAM_SWAP_BUFFERS		= 0x00000001L,

    /// Request an extra buffer for the previous source frame.
    FILTERPARAM_NEEDS_LAST			= 0x00000002L,

    /// Filter supports image formats other than RGB32. Filters that support format negotiation must
    /// set this flag for all calls to paramProc.
    FILTERPARAM_SUPPORTS_ALTFORMATS	= 0x00000004L,

    /// Filter requests 16 byte alignment for source and destination buffers. This guarantees that:
    ///
    ///		- data and pitch fields are multiples of 16 bytes (aligned)
    ///		- an integral number of 16 byte vectors may be read, even if the last vector includes
    ///		  some bytes beyond the end of the scanline (their values are undefined)
    ///		- an integral number of 16 byte vectors may be written, even if the last vector includes
    ///		  some bytes beyong the end of the scanline (their values are ignored)
    ///
    FILTERPARAM_ALIGN_SCANLINES		= 0x00000008L,

    /// Filter's output is purely a function of configuration parameters and source image data, and not
    /// source or output frame numbers. In other words, two output frames produced by a filter instance
    /// can be assumed to be identical images if:
    ///
    ///		- the same number of source frames are prefetched
    ///		- the same type of prefetches are performed (direct vs. non-direct)
    ///		- the frame numbers for the two prefetch lists, taken in order, correspond to identical
    ///		  source frames
    ///		- the prefetch cookies match
    ///
    /// Enabling this flag improves the ability of the host to identify identical frames and drop them
    /// in preview or in the output file.
    ///
    FILTERPARAM_PURE_TRANSFORM		= 0x00000010L,

    /// Filter cannot support the requested source format. Note that this sets all bits, so the meaning
    /// of other bits is ignored. The one exception is that FILTERPARAM_SUPPORTS_ALTFORMATS is assumed
    /// to be implicitly set.
    FILTERPARAM_NOT_SUPPORTED		= (long)0xFFFFFFFF
};

/// The filter has a delay from source to output. For instance, a lag of 3 indicates that the
/// filter internally buffers three frames, so when it is fed frames in sequence, frame 0 emerges
/// after frame 3 has been processed. The host attempts to correct timestamps in order to compensate.
///
/// VirtualDub 1.9.1 or later: Setting this flag can have a performance penalty, as it causes the host
/// to request additional frames to try to produce the correct requested output frames.
///
#define FILTERPARAM_HAS_LAG(frames) ((int)(frames) << 16)

///////////////////

class VDXFBitmap;
class VDXFilterActivation;
struct VDXFilterFunctions;
struct VDXFilterModule;
class IVDXVideoPrefetcher;

enum
{
    kVDXVFEvent_None				= 0,
    kVDXVFEvent_InvalidateCaches	= 1
};

typedef int (__cdecl *VDXFilterInitProc)(VDXFilterActivation *fa, const VDXFilterFunctions *ff);
typedef void (__cdecl *VDXFilterDeinitProc)(VDXFilterActivation *fa, const VDXFilterFunctions *ff);
typedef int (__cdecl *VDXFilterRunProc)(const VDXFilterActivation *fa, const VDXFilterFunctions *ff);
typedef long(__cdecl *VDXFilterParamProc)(VDXFilterActivation *fa, const VDXFilterFunctions *ff);
typedef int (__cdecl *VDXFilterConfigProc)(VDXFilterActivation *fa, const VDXFilterFunctions *ff, VDXHWND hWnd);
typedef void (__cdecl *VDXFilterStringProc)(const VDXFilterActivation *fa, const VDXFilterFunctions *ff, char *buf);
typedef int (__cdecl *VDXFilterStartProc)(VDXFilterActivation *fa, const VDXFilterFunctions *ff);
typedef int (__cdecl *VDXFilterEndProc)(VDXFilterActivation *fa, const VDXFilterFunctions *ff);
typedef bool (__cdecl *VDXFilterScriptStrProc)(VDXFilterActivation *fa, const VDXFilterFunctions *, char *, int);
typedef void (__cdecl *VDXFilterStringProc2)(const VDXFilterActivation *fa, const VDXFilterFunctions *ff, char *buf, int maxlen);
typedef int (__cdecl *VDXFilterSerialize)(VDXFilterActivation *fa, const VDXFilterFunctions *ff, char *buf, int maxbuf);
typedef void (__cdecl *VDXFilterDeserialize)(VDXFilterActivation *fa, const VDXFilterFunctions *ff, const char *buf, int maxbuf);
typedef void (__cdecl *VDXFilterCopy)(VDXFilterActivation *fa, const VDXFilterFunctions *ff, void *dst);
typedef sint64(__cdecl *VDXFilterPrefetch)(const VDXFilterActivation *fa, const VDXFilterFunctions *ff, sint64 frame);
typedef void (__cdecl *VDXFilterCopy2Proc)(VDXFilterActivation *fa, const VDXFilterFunctions *ff, void *dst, VDXFilterActivation *fa2, const VDXFilterFunctions *ff2);
typedef bool (__cdecl *VDXFilterPrefetch2Proc)(const VDXFilterActivation *fa, const VDXFilterFunctions *ff, sint64 frame, IVDXVideoPrefetcher *prefetcher);
typedef bool (__cdecl *VDXFilterEventProc)(const VDXFilterActivation *fa, const VDXFilterFunctions *ff, uint32 event, const void *eventData);

typedef int (__cdecl *VDXFilterModuleInitProc)(VDXFilterModule *fm, const VDXFilterFunctions *ff, int& vdfd_ver, int& vdfd_compat);
typedef void (__cdecl *VDXFilterModuleDeinitProc)(VDXFilterModule *fm, const VDXFilterFunctions *ff);

//////////

typedef void (__cdecl *VDXFilterPreviewButtonCallback)(bool fNewState, void *pData);
typedef void (__cdecl *VDXFilterPreviewSampleCallback)(VDXFBitmap *, long lFrame, long lCount, void *pData);

class IVDXFilterPreview
{
public:
    virtual void SetButtonCallback(VDXFilterPreviewButtonCallback, void *) = 0;
    virtual void SetSampleCallback(VDXFilterPreviewSampleCallback, void *) = 0;

    virtual bool isPreviewEnabled() = 0;
    virtual void Toggle(VDXHWND) = 0;
    virtual void Display(VDXHWND, bool) = 0;
    virtual void RedoFrame() = 0;
    virtual void RedoSystem() = 0;
    virtual void UndoSystem() = 0;
    virtual void InitButton(VDXHWND) = 0;
    virtual void Close() = 0;
    virtual bool SampleCurrentFrame() = 0;
    virtual long SampleFrames() = 0;
};

class IVDXFilterPreview2 : public IVDXFilterPreview
{
public:
    virtual bool IsPreviewDisplayed() = 0;
};

class IVDXVideoPrefetcher : public IVDXUnknown
{
public:
    enum { kIID = VDXMAKEFOURCC('X', 'v', 'p', 'f') };

    /// Request a video frame fetch from an upstream source.
    virtual void VDXAPIENTRY PrefetchFrame(sint32 srcIndex, sint64 frame, uint64 cookie) = 0;

    /// Request a video frame fetch from an upstream source in direct mode.
    /// This specifies that the output frame is the same as the input frame.
    /// There cannot be more than one direct fetch and there must be no standard
    /// fetches at the same time. There can, however, be symbolic fetches.
    virtual void VDXAPIENTRY PrefetchFrameDirect(sint32 srcIndex, sint64 frame) = 0;

    /// Request a symbolic fetch from a source. This does not actually fetch
    /// any frames, but marks an association from source to output. This is
    /// useful for indicating the approximate center of where an output derives
    /// in a source, even if those frames aren't fetched (perhaps due to caching).
    /// There may be either zero or one symbolic fetch per source.
    ///
    /// If no symbolic fetches are performed, the symbolic frame is assumed to
    /// be the rounded mean of the fetched source frames.
    virtual void VDXAPIENTRY PrefetchFrameSymbolic(sint32 srcIndex, sint64 frame) = 0;
};

//////////

enum
{
    // This is the highest API version supported by this header file.
    VIRTUALDUB_FILTERDEF_VERSION		= 14,

    // This is the absolute lowest API version supported by this header file.
    // Note that V4 is rather old, corresponding to VirtualDub 1.2.
    // Chances are you will need to declare a higher version.
    VIRTUALDUB_FILTERDEF_COMPATIBLE		= 4,

    // API V9 is a slightly saner baseline, since it is the first API
    // version that has copy constructor support. You may still need to
    // declare a higher vdfd_compat version in your module init if you
    // need features beyond V9 (VirtualDub 1.4.12).
    VIRTUALDUB_FILTERDEF_COMPATIBLE_COPYCTOR = 9

};

// v3: added lCurrentSourceFrame to FrameStateInfo
// v4 (1.2): lots of additions (VirtualDub 1.2)
// v5 (1.3d): lots of bugfixes - stretchblt bilinear, and non-zero startproc
// v6 (1.4): added error handling functions
// v7 (1.4d): added frame lag, exception handling
// v8 (1.4.11): added string2 proc
// v9 (1.4.12): added (working) copy constructor
// v10 (1.5.10): added preview flag
// v11 (1.7.0): guaranteed src structure setup before configProc; added IVDFilterPreview2
// v12 (1.8.0): support for frame alteration
// v13 (1.8.2): added mOutputFrame field to VDXFilterStateInfo
// v14 (1.9.1): added copyProc2, prefetchProc2, input/output frame arrays

struct VDXFilterDefinition
{
    void *_next;		// deprecated - set to NULL
    void *_prev;		// deprecated - set to NULL
    void *_module;		// deprecated - set to NULL

    const char *		name;
    const char *		desc;
    const char *		maker;
    void *				private_data;
    int					inst_data_size;

    VDXFilterInitProc		initProc;
    VDXFilterDeinitProc		deinitProc;
    VDXFilterRunProc		runProc;
    VDXFilterParamProc		paramProc;
    VDXFilterConfigProc		configProc;
    VDXFilterStringProc		stringProc;
    VDXFilterStartProc		startProc;
    VDXFilterEndProc		endProc;

    VDXScriptObject			*script_obj;

    VDXFilterScriptStrProc	fssProc;

    // NEW - 1.4.11
    VDXFilterStringProc2	stringProc2;
    VDXFilterSerialize		serializeProc;
    VDXFilterDeserialize	deserializeProc;
    VDXFilterCopy			copyProc;

    VDXFilterPrefetch		prefetchProc;		// (V12/V1.7.4+)

    // NEW - V14 / 1.9.1
    VDXFilterCopy2Proc		copyProc2;
    VDXFilterPrefetch2Proc	prefetchProc2;
    VDXFilterEventProc		eventProc;
};

//////////

// FilterStateInfo: contains dynamic info about file being processed

class VDXFilterStateInfo
{
public:
    sint32	lCurrentFrame;				// current sequence frame (previously called output frame)
    sint32	lMicrosecsPerFrame;			// microseconds per sequence frame
    sint32	lCurrentSourceFrame;		// current source frame
    sint32	lMicrosecsPerSrcFrame;		// microseconds per source frame
    sint32	lSourceFrameMS;				// source frame timestamp
    sint32	lDestFrameMS;				// output frame timestamp

    enum
    {
        kStateNone		= 0x00000000,
        kStatePreview	= 0x00000001,	// (V1.5.10+) Job output is not being saved to disk.
        kStateRealTime	= 0x00000002,	// (V1.5.10+) Operation is running in real-time (capture, playback).
        kStateMax		= 0xFFFFFFFF
    };

    uint32	flags;						// (V10 / 1.5.10+ only)

    sint32	mOutputFrame;				// (V13/V1.8.2+) current output frame
};

// VDXFBitmap: VBitmap extended to hold filter-specific information

class VDXBitmap
{
public:
    void *			_vtable;	// Reserved - do not use.
    uint32 *		data;		// Pointer to start of _bottom-most_ scanline of plane 0.
    uint32 *		palette;	// Pointer to palette (reserved - set to NULL).
    sint32			depth;		// Bit depth, in bits. Set to zero if mpPixmap/mpPixmapLayout are active.
    sint32			w;			// Width of bitmap, in pixels.
    sint32			h;			// Height of bitmap, in pixels.
    ptrdiff_t		pitch;		// Distance, in bytes, from the start of one scanline in plane 0 to the next.
    ptrdiff_t		modulo;		// Distance, in bytes, from the end of one scanline in plane 0 to the start of the next.
    ptrdiff_t		size;		// Size of plane 0, including padding.
    ptrdiff_t		offset;		// Offset from beginning of buffer to beginning of plane 0.

    uint32 *Address32(int x, int y) const
    {
        return Address32i(x, h - y - 1);
    }

    uint32 *Address32i(int x, int y) const
    {
        return (uint32 *)((char *)data + y * pitch + x * 4);
    }

    void AlignTo4()
    {
        pitch = w << 2;
    }

    void AlignTo8()
    {
        pitch = ((w + 1)&~1) << 2;
    }
};

class VDXFBitmap : public VDXBitmap
{
public:
    enum
    {
        /// Set in paramProc if the filter requires a Win32 GDI display context
        /// for a bitmap. (Deprecated as of API V12 - do not use)
        NEEDS_HDC		= 0x00000001L,
    };

    uint32		dwFlags;
    VDXHDC		hdc;

    uint32	mFrameRateHi;		// Frame rate numerator (V1.7.4+)
    uint32	mFrameRateLo;		// Frame rate denominator (V1.7.4+)
    sint64	mFrameCount;		// Frame count; -1 if unlimited or indeterminate (V1.7.4+)

    VDXPixmapLayout	*mpPixmapLayout;
    const VDXPixmap	*mpPixmap;

    uint32	mAspectRatioHi;				///< Pixel aspect ratio fraction (numerator).	0/0 = unknown
    uint32	mAspectRatioLo;				///< Pixel aspect ratio fraction (denominator).

    sint64	mFrameNumber;				///< Current frame number (zero based).
    sint64	mFrameTimestampStart;		///< Starting timestamp of frame, in 100ns units.
    sint64	mFrameTimestampEnd;			///< Ending timestamp of frame, in 100ns units.
    sint64	mCookie;					///< Cookie supplied when frame was requested.
};

// VDXFilterActivation: This is what is actually passed to filters at runtime.

class VDXFilterActivation
{
public:
    const VDXFilterDefinition *filter;		//
    void *filter_data;
    VDXFBitmap&	dst;
    VDXFBitmap&	src;
    VDXFBitmap	*_reserved0;
    VDXFBitmap	*const last;
    uint32		x1;
    uint32		y1;
    uint32		x2;
    uint32		y2;

    VDXFilterStateInfo	*pfsi;
    IVDXFilterPreview	*ifp;
    IVDXFilterPreview2	*ifp2;			// (V11+)

    uint32		mSourceFrameCount;		// (V14+)
    VDXFBitmap *const *mpSourceFrames;	// (V14+)
    VDXFBitmap *const *mpOutputFrames;	// (V14+)
};

// These flags must match those in cpuaccel.h!

#ifndef f_VIRTUALDUB_CPUACCEL_H
#define CPUF_SUPPORTS_CPUID			(0x00000001L)
#define CPUF_SUPPORTS_FPU			(0x00000002L)
#define CPUF_SUPPORTS_MMX			(0x00000004L)
#define CPUF_SUPPORTS_INTEGER_SSE	(0x00000008L)
#define CPUF_SUPPORTS_SSE			(0x00000010L)
#define CPUF_SUPPORTS_SSE2			(0x00000020L)
#define CPUF_SUPPORTS_3DNOW			(0x00000040L)
#define CPUF_SUPPORTS_3DNOW_EXT		(0x00000080L)
#endif

struct VDXFilterFunctions
{
    VDXFilterDefinition *(__cdecl *addFilter)(VDXFilterModule *, VDXFilterDefinition *, int fd_len);
    void (__cdecl *removeFilter)(VDXFilterDefinition *);
    bool (__cdecl *isFPUEnabled)();
    bool (__cdecl *isMMXEnabled)();
    void (__cdecl *InitVTables)(VDXFilterVTbls *);

    // These functions permit you to throw MyError exceptions from a filter.
    // YOU MUST ONLY CALL THESE IN runProc, initProc, and startProc.

    void (__cdecl *ExceptOutOfMemory)();						// ADDED: V6 (VirtualDub 1.4)
    void (__cdecl *Except)(const char *format, ...);			// ADDED: V6 (VirtualDub 1.4)

    // These functions are callable at any time.

    long(__cdecl *getCPUFlags)();								// ADDED: V6 (VirtualDub 1.4)
    long(__cdecl *getHostVersionInfo)(char *buffer, int len);	// ADDED: V7 (VirtualDub 1.4d)
};





///////////////////////////////////////////////////////////////////////////

class VDXScriptValue;
class VDXScriptError;
struct VDXScriptObject;

class VDXScriptError
{
public:
    enum
    {
        PARSE_ERROR = 1,
        SEMICOLON_EXPECTED,
        IDENTIFIER_EXPECTED,

        TYPE_INT_REQUIRED,
        TYPE_ARRAY_REQUIRED,
        TYPE_FUNCTION_REQUIRED,
        TYPE_OBJECT_REQUIRED,

        OBJECT_MEMBER_NAME_REQUIRED,
        FUNCCALLEND_EXPECTED,
        TOO_MANY_PARAMS,
        DIVIDE_BY_ZERO,
        VAR_NOT_FOUND,
        MEMBER_NOT_FOUND,
        OVERLOADED_FUNCTION_NOT_FOUND,
        IDENT_TOO_LONG,
        OPERATOR_EXPECTED,
        CLOSEPARENS_EXPECTED,
        CLOSEBRACKET_EXPECTED,

        VAR_UNDEFINED,

        OUT_OF_STRING_SPACE,
        OUT_OF_MEMORY,
        INTERNAL_ERROR,
        EXTERNAL_ERROR,

        FCALL_OUT_OF_RANGE,
        FCALL_INVALID_PTYPE,
        FCALL_UNKNOWN_STR,

        ARRAY_INDEX_OUT_OF_BOUNDS,

        NUMERIC_OVERFLOW,
        STRING_NOT_AN_INTEGER_VALUE,
        STRING_NOT_A_REAL_VALUE,

        ASSERTION_FAILED,
        AMBIGUOUS_CALL,
        CANNOT_CAST
    };
};

class IVDXScriptInterpreter
{
public:
    virtual	void _placeholder1() {}
    virtual void _placeholder2(void *, void *) {}
    virtual void _placeholder3(char *s) {}

    virtual void ScriptError(int e) = 0;
    virtual void _placeholder4(VDXScriptError& cse) {}
    virtual char** AllocTempString(long l) = 0;

    virtual void _placeholder5() {}
};

#define EXT_SCRIPT_ERROR(x)	(isi->ScriptError((VDXScriptError::x)))

typedef VDXScriptValue(*VDXScriptFunctionPtr)(IVDXScriptInterpreter *, void *, const VDXScriptValue *, int);
typedef void (*VDXScriptVoidFunctionPtr)(IVDXScriptInterpreter *, void *, const VDXScriptValue *, int);
typedef int (*VDXScriptIntFunctionPtr)(IVDXScriptInterpreter *, void *, const VDXScriptValue *, int);

struct VDXScriptFunctionDef
{
    VDXScriptFunctionPtr func_ptr;
    char *name;
    char *arg_list;
};

struct VDXScriptObject
{
    void *_lookup;							// reserved - set to NULL
    VDXScriptFunctionDef	*func_list;
    void *_obj_list;						// reserved - set to NULL
};

class VDXScriptValue
{
public:
    enum { T_VOID, T_INT, T_PINT, T_STR, T_ARRAY, T_OBJECT, T_FNAME, T_FUNCTION, T_VARLV, T_LONG, T_DOUBLE } type;
    VDXScriptObject *thisPtr;
    union
    {
        int i;
        char **s;
        sint64 l;
        double d;
    } u;

    VDXScriptValue()
    {
        type = T_VOID;
    }
    VDXScriptValue(int i)
    {
        type = T_INT;
        u.i = i;
    }
    VDXScriptValue(sint64 l)
    {
        type = T_LONG;
        u.l = l;
    }
    VDXScriptValue(double d)
    {
        type = T_DOUBLE;
        u.d = d;
    }
    VDXScriptValue(char **s)
    {
        type = T_STR;
        u.s = s;
    }

    bool isVoid() const
    {
        return type == T_VOID;
    }
    bool isInt() const
    {
        return type == T_INT;
    }
    bool isString() const
    {
        return type == T_STR;
    }
    bool isLong() const
    {
        return type == T_LONG;
    }
    bool isDouble() const
    {
        return type == T_DOUBLE;
    }

    int		asInt() const
    {
        return u.i;
    }
    sint64	asLong() const
    {
        return u.l;
    }
    double	asDouble() const
    {
        return u.d;
    }
    char **	asString() const
    {
        return u.s;
    }
};

#ifdef _MSC_VER
#pragma pack(pop)
#endif

#endif
